package com.jimo.app.util;

import android.os.Build;

import androidx.annotation.RequiresApi;

import java.io.*;
import java.util.Map;
import java.util.zip.*;

public class ApkUtils {
    @RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
    public static void addOrReplaceFiles(File apkFile, Map<String, byte[]> filesToAdd) throws IOException {
        File tempFile = new File(apkFile.getParent(), "tmp_" + apkFile.getName());
        try (ZipInputStream zis = new ZipInputStream(new FileInputStream(apkFile));
             ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(tempFile))) {

            ZipEntry entry;
            byte[] buffer = new byte[4096];

            // 复制原有文件，排除要替换的
            while ((entry = zis.getNextEntry()) != null) {
                if (!filesToAdd.containsKey(entry.getName())) {
                    ZipEntry newEntry = new ZipEntry(entry.getName());

                    // 如果是 resources.arsc，使用 STORED 不压缩
                    if ("resources.arsc".equals(entry.getName())) {
                        byte[] data = zis.readAllBytes();
                        newEntry.setMethod(ZipEntry.STORED);
                        newEntry.setSize(data.length);
                        newEntry.setCompressedSize(data.length);
                        newEntry.setCrc(crc32(data));
                        zos.putNextEntry(newEntry);
                        zos.write(data);
                    } else {
                        zos.putNextEntry(newEntry);
                        int len;
                        while ((len = zis.read(buffer)) > 0) {
                            zos.write(buffer, 0, len);
                        }
                    }
                    zos.closeEntry();
                }
            }

            for (Map.Entry<String, byte[]> e : filesToAdd.entrySet()) {
                ZipEntry newEntry = new ZipEntry(e.getKey());
                zos.putNextEntry(newEntry);
                zos.write(e.getValue());
                zos.closeEntry();
            }
        }

        // 替换原文件
        if (!apkFile.delete() || !tempFile.renameTo(apkFile)) {
            throw new IOException("替换 APK 失败");
        }
    }

    private static long crc32(byte[] data) {
        java.util.zip.CRC32 crc = new java.util.zip.CRC32();
        crc.update(data);
        return crc.getValue();
    }

}
